package main

import (
	"context"
	"net"

	"gofw-im/lib/define"
	pb "gofw-im/lib/grpc"
	"gofw-im/lib/logger"
	inet "gofw-im/lib/net"
	"gofw-im/lib/proto"

	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

func InitGrpc() (err error) {
	var (
		network, addr string
	)
	if network, addr, err = inet.ParseNetwork(conf.Base.rpcAddr); err != nil {
		logger.Error.Printf("InitGrpc ParseNetwork error : %s", err)
		return
	}
	go createServer(network, addr)
	return
}

func createServer(network string, addr string) {
	lis, err := net.Listen(network, addr)
	if err != nil {
		logger.Error.Printf("InitGrpc failed to listen : %s", err)
		return
	}
	s := grpc.NewServer()
	pb.RegisterCometServer(s, &server{})
	reflection.Register(s)
	s.Serve(lis)
}

type server struct{}

func (rpc *server) MPushMsg(ctx context.Context, request *pb.PushMsgArg) (response *pb.SuccessReply, err error) {
	logger.Info.Printf("rpc MPushMsg :%v ", request)
	if request == nil {
		logger.Error.Printf("rpc MPushMsg() error(%v)", ErrRpcRequestNil)
		return nil, ErrRpcRequestNil
	}
	return
}

func (rpc *server) PushMsg(ctx context.Context, request *pb.PushMsgArg) (response *pb.SuccessReply, err error) {
	var (
		bucket  *Bucket
		channel *Channel
	)
	logger.Info.Printf("rpc PushMsg :%v ", request)
	if request == nil {
		logger.Error.Printf("rpc PushSingleMsg() error(%v)", ErrRpcRequestNil)
		return nil, ErrRpcRequestNil
	}
	bucket = defaultServer.Bucket(request.Uid)
	if channel = bucket.Channel(request.Uid); channel != nil {
		err = channel.Push(&proto.Proto{
			Ver:       int16(request.P.Ver),
			Operation: request.P.Operation,
			Body:      request.P.Body,
		})
		logger.Info.Printf("DefaultServer Channel err nil : %v", err)
	}
	response = &pb.SuccessReply{
		Code: define.SUCCESS_REPLY,
		Msg:  define.SUCCESS_REPLY_MSG,
	}
	return
}

func (rpc *server) PushRoomMsg(ctx context.Context, request *pb.RoomMsgArg) (response *pb.SuccessReply, err error) {
	roomMsgArg := &proto.RoomMsgArg{
		RoomId: request.RoomId,
		P: proto.Proto{
			Ver:       int16(request.P.Ver),
			Operation: request.P.Operation,
			Body:      request.P.Body,
		},
	}
	for _, bucket := range defaultServer.Buckets {
		bucket.BroadcastRoom(roomMsgArg)
	}
	response = &pb.SuccessReply{
		Code: define.SUCCESS_REPLY,
		Msg:  define.SUCCESS_REPLY_MSG,
	}
	return
}

func (rpc *server) PushRoomCount(ctx context.Context, request *pb.RoomMsgArg) (response *pb.SuccessReply, err error) {
	logger.Info.Printf("PushRoomCount count %v", request)
	roomMsgArg := &proto.RoomMsgArg{
		RoomId: request.RoomId,
		P: proto.Proto{
			Ver:       int16(request.P.Ver),
			Operation: request.P.Operation,
			Body:      request.P.Body,
		},
	}
	for _, bucket := range defaultServer.Buckets {
		bucket.BroadcastRoom(roomMsgArg)
		// room.next

	}
	response = &pb.SuccessReply{
		Code: define.SUCCESS_REPLY,
		Msg:  define.SUCCESS_REPLY_MSG,
	}
	return
}

/**
广播房间信息
*/
func (rpc *server) PushRoomInfo(ctx context.Context, request *pb.RoomMsgArg) (response *pb.SuccessReply, err error) {
	logger.Info.Printf("PushRoomInfo  %v", request)
	roomMsgArg := &proto.RoomMsgArg{
		RoomId: request.RoomId,
		P: proto.Proto{
			Ver:       int16(request.P.Ver),
			Operation: request.P.Operation,
			Body:      request.P.Body,
		},
	}
	for _, bucket := range defaultServer.Buckets {
		bucket.BroadcastRoom(roomMsgArg)
		// room.next
	}
	response = &pb.SuccessReply{
		Code: define.SUCCESS_REPLY,
		Msg:  define.SUCCESS_REPLY_MSG,
	}
	return
}
